home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / BootX 1.2.2 / Sources / lib / MoreCFMPatches / MoreCFMPatches.s < prev    next >
Text File  |  2001-07-23  |  6KB  |  149 lines

  1. #    File:        MoreCFMPatches.s
  2. #
  3. #    Contains:    Assembly language stuff for the CFM patching library.
  4. #
  5. #    Written by:    Quinn
  6. #
  7. #    Copyright:    Copyright ゥ 1998-1999 by Apple Computer, Inc., all rights reserved.
  8. #
  9. #                You may incorporate this Apple sample source code into your program(s) without
  10. #                restriction. This Apple sample source code has been provided "AS IS" and the
  11. #                responsibility for its operation is yours. You are not permitted to redistribute
  12. #                this Apple sample source code as "Apple sample source code" after having made
  13. #                changes. If you're going to re-distribute the source, we require that you make
  14. #                it clear in the source that the code was descended from Apple sample source
  15. #                code, but that you've made changes.
  16. #
  17. #    Change History (most recent first):
  18. #
  19. #        <2>     16/3/99    Quinn   Fix checkin comment.
  20. #        <1>     16/3/99    Quinn   First checked in.
  21. #
  22.  
  23. # IMPORTANT:
  24. # Each instruction is commented with its offset from the beginning
  25. # of the routine, and hence the offset into the C PatchIsland
  26. # data structure.  Rather than comment line-by-line, I've included
  27. # comments at the end of the file.  These comments reference the
  28. # instructions by their offset.
  29.  
  30. # Constants shared with "MoreCFMPatches.c".  If you change them
  31. # here, you must also change them there.
  32.  
  33. kSystemReservedFrameOffset    equ        16
  34. kPatchIslandSignature         equ        'Nat!'
  35. kPatchRecordSize            equ        16
  36.  
  37. # TVector for the MorePatchCallThrough routine.
  38.  
  39.         csect    MoreCFMPatchesCallThrough{DS}
  40.         export    MoreCFMPatchesCallThrough{DS}
  41.         dc.l    .MoreCFMPatchesCallThrough{PR}
  42.         dc.l    toc{tc0}
  43.  
  44. # Patch island code
  45.  
  46.         csect    .MoreCFMPatchesCallThrough{PR}
  47.         export    .MoreCFMPatchesCallThrough{PR}
  48.  
  49. # Local labels correspond to field names in the C PatchIsland data structure.
  50.  
  51. callThrough:
  52.         lwz            r11,0(sp)                                # 0
  53.         lwz            r11,kSystemReservedFrameOffset(r11)        # 4
  54.         addi        r11,r11,kPatchRecordSize                # 8
  55.         b            PatchIslandCommon                        # 12
  56. signature
  57.         dc.l        kPatchIslandSignature                    # 16
  58. patchIslandEntry:
  59.         lis            r11,0                                    # 20
  60.         ori            r11,r11,0                                # 24
  61. patchIslandCommon:
  62.         lwz            r0,0(r11)                                # 28
  63.         lwz            r12,4(r11)                                # 32
  64.         mtctr        r0                                        # 36
  65.         stw            r11,kSystemReservedFrameOffset(sp)        # 40
  66.         lwz            RTOC,4(r12)                                # 44
  67.         bctr                                                # 48
  68.                                                             # 52
  69.         toc
  70.  
  71.         end
  72.  
  73. # Stuff after the "end" directive is ignored by the assembler.
  74.  
  75. How and Why
  76. -----------
  77.  
  78. To understand this code you must understand three key things about
  79. how CFM uses TVectors, as described in the "MoreCFMPatches.h" header
  80. file:
  81.  
  82. //      a) the first word must point to the code,
  83. //      b) the caller must load the second word into R2, and
  84. //      c) the caller must load R12 with a pointer to the TVector itself.
  85. //         [This allows the callee to extract any extra information
  86. //          it cares to store in the TVector.]
  87.  
  88. This patch island must preserve these invariants.
  89.  
  90. There are two basic threads of execution.  When the patched routine
  91. is first called, we enter at patchIslandEntry.  The next two
  92. instructions (offsets 20 and 24) comprise the patch island payload.
  93. [The term "payload" is explained in "MoreCFMPatches.c".]  As written
  94. here, they load R11 with a constant 0.  However, when we build
  95. a patch island, we modify these instruction to load R11 with a
  96. pointer to the first patch record in the patch island (which is
  97. actually at offset 52, although this code doesn't know that).  Once
  98. we have R11 set to the 'current' patch record, we fall through
  99. to patchIslandCommon (offset 28), which does the bulk of the work.
  100.  
  101.     Note:
  102.     PowerPC calling conventions on the Mac OS say that R11
  103.     is free for uses such as these.  See "Mac OS Runtime
  104.     Architectures" <http://www.apple.com/developer/> for
  105.     details.
  106.  
  107. The second entry point is callThrough, which is called when a
  108. patch calls gMoreCFMPatchesCallThrough.  The goal of this
  109. entry point is to call through to the next patch record in the
  110. patch chain.  To that end, it must load R11 with the address
  111. of that patch record and then 'fall' through to patchIslandCommon
  112. (offset 28), which does the bulk of the work.
  113.  
  114. callThrough gets the appropriate patch record from the stack frame
  115. of the callee (not the patch routine that's calling
  116. gMoreCFMPatchesCallThrough, but the person who called the patch).
  117. The instruction at offset 0 loads R11 with the callee's 'frame' pointer,
  118. ie the value of SP that the patch routine's preamble saved there.
  119. The next instruction (offset 4) gets the current patch record
  120. pointer into R11 by extracting it from the system reserved frame
  121. offset in the callee's stack frame.  Next (offset 8), callThrough
  122. increments that pointer by the size of the patch record, to shuffle 
  123. along to the next patch record in the chain.  Finally (offset 12),
  124. it branches to patchIslandCommon (offset 28).
  125.  
  126. patchIslandCommon is the guts behind the patch island.  The input
  127. parameter is R11, a pointer to the patch record we wish to invoke.
  128. [As explained in "MoreCFMPatches.c", the last patch record actually
  129. describes the original patched routine, but the logic works in
  130. that case as well.]  patchIslandCommon starts (offset 28) by
  131. loading R0 with the patch code pointer from the patch record
  132. pointed to by R11.  [In C this is the patchCode field of the
  133. PatchRecord type.]  It then (offset 32) loads R12 with the TVector
  134. pointer of the patch record.  [In C this is the patchTVector field
  135. of the PatchRecord type.]  Remember, the Mac OS runtime requires
  136. that, when a routine is entered, R12 must always be a pointer
  137. to its TVector, so that the routine can extract extra information
  138. from the TVector.  Then (offset 36) we move R0 (the code pointer)
  139. into the counter register, in preparation for a branch to it (offset 48).
  140. But before that (offset 40), we store the R11 into the current frame,
  141. which allows callThrough to extract it from this frame if the patch
  142. calls gMoreCFMPatchesCallThrough.  Finally (offset 44), we load RTOC with
  143. the second word of the TVector (this is also required by the runtime
  144. architecture) and then branch (offset 48) to the patch code, whose
  145. address is in the counter register (put there by the instruction at
  146. offset 36).
  147.  
  148. Neat huh?
  149.